﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using dotnetCHARTING.WinForms;


namespace OEMS
{
    public partial class VisualisatieForm : Form
    {

        private Color[] kleurenLijst;


        //CONSTRUCTOR
        public VisualisatieForm(int gegevensID)
        {
            InitializeComponent();

            this.CreateChart(chart1, gegevensID);

        }


        /// <summary>
        /// Methode die de grafiek 
        /// </summary>
        /// <param name="gegevensID">a</param>
        /// <author>Mathieu Cruts</author>
        public void CreateChart(Chart chart1, int gegevensID)
        {
            SeriesCollection seriesCollection;
            Series series = new Series();

            // CONFIGURE
            this.setGraphStandards(chart1);
            this.setGraphSettings(chart1);
            
            // IMPORT DATA
            seriesCollection = ImportData(gegevensID);

            // COLOR PALETTE
            this.chart1 = createColorPalette(chart1, seriesCollection);

            // ADD DATA
            this.chart1.SeriesCollection.Add(seriesCollection);

            // ADD CONTOUR
            series = addContour(series);
            this.chart1.SeriesCollection.Add(series);


        }


        private Series addContour(Series series)
        {
            // We add an additional series with no data to layer an additional layer style (contour)
            series.Type = SeriesTypeSurface.Contour;
            series.Background.Transparency = 80;
            series.Line.Color = Color.Black;
            series.Line.Transparency = 70;

            return series;
        }


        private Chart setGraphStandards(Chart chart)
        {
            chart.Width = 1024;
            chart.Height = 550;
            chart.MarginTop = 60;
            chart.LegendBox.Visible = false;
            chart.Type = ChartType.Surface;
            //coloring while knowing the values around the current cell)
            chart.DefaultSeries.InterpolationFillFactor = 5;

            return chart;
        }


        private Chart setGraphSettings(Chart chart)
        {
            chart1.XAxis.Interval = Convert.ToDouble(Properties.Settings.Default.xAxisInterval);
            chart1.YAxis.Interval = Convert.ToDouble(Properties.Settings.Default.yAxisInterval);

            return chart;
        }


        private Color[] getColorArrayFromSettings(int length)
        {
            kleurenLijst = new Color[length];
            Color kleur;

            for (int i = 0; i < length; i++)
            {
                try 
	            {
                    kleur = new Color();
                    kleur = Color.FromName(Properties.Settings.Default.GraphColors[i]);
                    kleurenLijst[i] = kleur;
            	}
            	catch (Exception)
	            {
		            MessageBox.Show("Kleurconversie fout");
	            }

            }

            return kleurenLijst;
        }


        private Chart createColorPalette(Chart chart, SeriesCollection seriesCollection)
        {
            int aantalKleuren = Properties.Settings.Default.GraphColors.Count;

            // Sets a palette of colors and adds it to our seriescollection
            chart.SmartPalette = seriesCollection[0].GetSmartPalette(ElementValue.ZValue, getColorArrayFromSettings(aantalKleuren));

            // Creates a bar with the used colors and their starting values + adds it to the chart
            Annotation an = new Annotation(createColorPalette(750, chart.SmartPalette, aantalKleuren, true));
            an.Position = new Point(25, 10);
            an.DynamicSize = false;
            chart.Annotations.Add(an);

            return chart;
        }

        /// <summary>
        /// Method die alle data importeert voor de grafiek
        /// </summary>
        /// <param name="gegevensID">a</param>
        /// <author>Mathieu Cruts</author>
        private SeriesCollection ImportData(int gegevensID)
        {
            SeriesCollection SC = new SeriesCollection();
            Series series;

            Motor motor = new Motor();
            Meting[] motorMetingen = MetingDB.GetMetingenArray(gegevensID);

            double[] yVals = new double[1764];
            double[] xVals = new double[1764];
            double[][] zVals = new double[42][];

            int counter = 0;

            // X- en Y-waardes vullen
            for (int i = 0; i < 1764; i++)
            {
                yVals[i] = Convert.ToDouble(motorMetingen[i].Toerental);
                xVals[i] = Convert.ToDouble(motorMetingen[i].Moment);

            }

            // Z-waardes vullen
            for (int i = 0; i < 42; i++)
            {
                zVals[i] = new double[42];

                for (int j = 0; j < 42; j++)
                {
                    zVals[i][j] = Convert.ToDouble(motorMetingen[counter].Rendement);
                    counter++;
                }
            }

            // Zorgt dat er geen dubbele waardes zijn en ze kolom per kolom worden ingelezen
            xVals = readByColumn(getDistinctKoppel(xVals), 21);

            // Geeft de data aan een serie door, die op zijn beurt wordt doorgegeven aan de seriescollectie
            series = Series.FromSurfaceData("", xVals, yVals, zVals);
            SC.Add(series);

            //transparency of our grid
            SC[0].Line.Transparency = 65;

            return SC;
        }


        /// <summary>
        /// Creeert een kleurenpalette om boven de grafiek weer te geven
        /// </summary>
        /// <param name="width">breedte van het gehele kleurenpalette</param>
        /// <param name="smartPalette">smartpalette met de kleuren en waardes</param>
        /// <param name="divisions">aantal verdelingen</param>
        /// <param name="withValues">al dan niet de overgangen van de waardes weergeven</param>
        /// <author>dotnetcharting</author>
        private String createColorPalette(int width, SmartPalette smartPalette, int divisions, bool withValues)
        {
            // Get Maximum Value of the smart palette range
            double max = (double)smartPalette.GetScaleRange("*").ValueHigh;
            double min = (double)smartPalette.GetScaleRange("*").ValueLow;

            string colorHtmlString = "", spacerString = "";
            double step = (max - min) / divisions;

            // Width of each division.
            int boxWidth = width / divisions;

            // Generate swatch string for each division.
            for (int i = 0; i < divisions; i++)
            {
                spacerString += "<Chart:Spacer size='" + boxWidth + "x1'>";

                // Get the color of the current division.
                string color = getHTMLColor(smartPalette.GetValueColor("", min + (i * (step))));

                if (withValues)
                {
                    double value = Math.Round((min + (i * (step))), 2);
                    double nextValue = Math.Round(((value + step) - 1), 2);

                    if (value < 0)
                    {
                        value = 0;
                    }

                    colorHtmlString += "<block hAlignment='Center' bgColor='" + color + "'>" + value + "  -  " + nextValue + " ";
                    }
                    else
                    {
                        colorHtmlString += "<block bgColor='" + color + "' fColor='" + color + "'>_";
                    }

            }

            //return the swatch string.
            return spacerString + "<row>" + colorHtmlString;
        }


        /// <summary>
        /// Kleuren worden geconverteerd naar hun hexadecimale HTML-waarde
        /// </summary>
        /// <param name="color">de om te vormen kleur</param>
        /// <author>dotnetcharting</author>
        string getHTMLColor(Color color)
        {
            return "#" + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2"); // X2 maakt er 2 getallen van zodat het geheel een hexadecimale HTML-code wordt
        }


        /// <summary>
        /// De dubbels van kolom A tot V worden éénmaal ingelezen, gevolgd door alle andere waarden
        /// </summary>
        /// <param name="koppelArray">array met alle data</param>
        /// <author>Mathieu Cruts</author>
        private double[] getDistinctKoppel(double[] koppelArray)
        {
            double[] data = new double[882];
            int counter = 0;

            for (int i = 21; i < koppelArray.Length; i++)
            {
                if ((i / 21) % 2 == 1)
                {
                    for (int j = 0; j < 21; j++)
                    {
                        data[counter] = koppelArray[(i + j)];
                        counter++;
                    }

                    i += 21;
                }

            }
            return data;
        }


        /// <summary>
        /// Gegevens uit een array worden omgevormd alsof ze kolom per kolom werden ingelezen ipv rij per rij
        /// </summary>
        /// <param name="koppelArray">array met de data</param>
        /// <param name="columnAmount">aantal kolommen waarin de data verdeeld moet worden</param>
        /// <author>Mathieu Cruts</author>
        private double[] readByColumn(double[] koppelArray, int columnAmount)
        {
            int counter = 0;
            List<double> list = new List<double>();
            list.Add(koppelArray[0]);

            for (int i = 0; i < columnAmount; i++)
            {
                counter = i;

                do
                {
                    list.Add(koppelArray[counter]);
                    System.Diagnostics.Debug.WriteLine(koppelArray[counter]);
                    counter += columnAmount;

                } while (counter < koppelArray.Length);
            }

            return list.ToArray();
        }


        private void saveGraphOnComputer(Chart chart, String fileName)
        {
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            Bitmap bmp;
            DialogResult result;
            String fullPath;
            
            folderDlg.ShowNewFolderButton = true;

            result = folderDlg.ShowDialog();
            
            if (result == DialogResult.OK)
            {
                chart.TempDirectory = folderDlg.SelectedPath;
                fullPath = folderDlg.SelectedPath + "/" + fileName;
                chart.ImageFormat = dotnetCHARTING.WinForms.ImageFormat.Bmp;

                bmp = chart.GetChartBitmap();
                bmp.Save(fullPath, System.Drawing.Imaging.ImageFormat.Bmp);
            }
        }


        private Bitmap saveGraphAsBitmap(Chart chart)
        {
            Bitmap bmp = chart.GetChartBitmap();

            return bmp;
        }


        private void button1_Click(object sender, EventArgs e)
        {
            saveGraphOnComputer(chart1, "test.bmp");
        }


        private void button2_Click(object sender, EventArgs e)
        {
            Bitmap test = saveGraphAsBitmap(chart1);
            pictureBox1.BackgroundImage = test;
        }



    }
}
